package com.squareshoot.picCheckin;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.LinkedHashMap;

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.ImageView;

public class PhotosDownloader {

	private boolean cacheOnSD;
	private boolean roundCorners;
	private int HASH_CAPACITY = 20;
	Bitmap image;

	public PhotosDownloader(boolean cacheOnSd,boolean round,Drawable d){
		this.cacheOnSD=cacheOnSd;
		this.image=((BitmapDrawable)d).getBitmap();
		this.roundCorners=round;
	}

	//	HashMap<String,SoftReference<Bitmap>> photos = new HashMap<String, SoftReference<Bitmap>>(HASH_CAPACITY);
	LinkedHashMap<String,SoftReference<Bitmap>> photos = new LinkedHashMap<String, SoftReference<Bitmap>>(HASH_CAPACITY,0.75f,false);

	public void getPhoto(String url, ImageView imageView) {
		Bitmap bm = getFromCache(url);

		if(bm!=null){ //Image dans la HashMap, on ne telecharge pas.
			cancelPotentialDownload(url, imageView);
			applyImage(imageView,bm);
		}else{ //Image pas en memoire, ni sur la sdcard
			if (cancelPotentialDownload(url, imageView)) {
				BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
				DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
				imageView.setImageDrawable(downloadedDrawable);
				task.execute(url);
			}
		}
	}

	private Bitmap getFromCache(String url){
		SoftReference<Bitmap> bitmapReference = photos.get(url);
		Bitmap bitmap=null;
		if (bitmapReference != null) {
			bitmap = bitmapReference.get();
			if (bitmap != null) {
				// Bitmap trouve dans la HashMap
				//				Log.d(Common.TAG,"GOT FROM HASH "+url);
				return bitmap;
			} else {
				// Soft reference has been Garbage Collected
				photos.remove(url);
			}
		}

		try {
			bitmap=Common.getImagefromSD(url);
			if(bitmap!=null){
				addBitmaptoHash(url,bitmap);
				//				Log.d(Common.TAG,"GOT FROM SD "+url);
				return bitmap;
			}
		} catch (IOException e) {
			return null;
		}

		return null;
	}

	private void addBitmaptoHash(String url,Bitmap bm){
		SoftReference<Bitmap> sBm = new SoftReference<Bitmap>(bm);
		photos.put(url,sBm);
	}

	class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
		private final WeakReference<ImageView> imageViewReference;
		String url;

		public BitmapDownloaderTask(ImageView imageView) {
			imageViewReference = new WeakReference<ImageView>(imageView);
		}

		protected Bitmap doInBackground(String... params) {
			url = params[0];
			Bitmap bm = null;
			try {
				bm = Common.downloadImage(url);
			} catch (IOException e) {
				e.printStackTrace();
			}

			return bm;
		}

		protected void onPostExecute(Bitmap bitmap) {
			//	    	Log.d(Common.TAG,"DOWNLOADED "+url);
			if (isCancelled()) {
				bitmap = null;
			}

			addBitmaptoHash(url,bitmap);
			if(cacheOnSD && bitmap!=null)
				Common.savePicture(bitmap, url);

			if (imageViewReference != null) {
				ImageView imageView = imageViewReference.get();
				BitmapDownloaderTask dlTask = getBitmapDownloaderTask(imageView);
				// Change bitmap only if this process is still associated with it
				if (this == dlTask) {
					applyImage(imageView,bitmap);
				}
			}
		}
	}

	private static boolean cancelPotentialDownload(String url, ImageView imageView) {
		BitmapDownloaderTask dlTask = getBitmapDownloaderTask(imageView);

		if (dlTask != null) {
			String bitmapUrl = dlTask.url;
			if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
				dlTask.cancel(true);
			} else {
				// The same URL is already being downloaded.
				return false;
			}
		}
		return true;
	}

	private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
		if (imageView != null) {
			Drawable drawable = imageView.getDrawable();
			if (drawable instanceof DownloadedDrawable) {
				DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
				return downloadedDrawable.getBitmapDownloaderTask();
			}
		}
		return null;
	}

	protected class DownloadedDrawable extends BitmapDrawable {
		private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

		public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
			super(image);

			bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
		}

		public BitmapDownloaderTask getBitmapDownloaderTask() {
			return bitmapDownloaderTaskReference.get();
		}
	}

	private void applyImage(ImageView iv,Bitmap bm){
		if(roundCorners && bm!=null)
			iv.setImageBitmap(Common.getRoundedCornerBitmap(bm));
		else
			iv.setImageBitmap(bm);
	}
}
